import logging
from datetime import timedelta

import jwt
from django.db import DatabaseError
from django.db.models import Q
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render, redirect
from django.utils import timezone

from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from django_redis import get_redis_connection
from rest_framework.decorators import api_view
from rest_framework.generics import ListAPIView
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet

from teamwork import settings
from user.models import Post, Comment, News, User
from user.serializers import PostSerializer, CommentSerializer, NewsSerializer, UserSerializer
from user.utils import check_username, check_password, gen_sha256_digest, check_tel


def show_index(request):
    """论坛首页"""
    return redirect('/static/html/post.html')


class PostView(ListAPIView):
    # 指定如何获取数据
    queryset = Post.objects.all()
    # 指定如何序列化数据
    serializer_class = PostSerializer


@api_view(('GET', ))
def show_comments(request):
    """获取帖子评论"""
    try:
        postid = int(request.GET['postid'])
        post = Post.objects.only('post_title').get(postid=postid)
        queryset = Comment.objects.filter(post_id=postid)
        serializer = CommentSerializer(queryset, many=True)
        data = {
            'code': 20000,
            'post': {'id': post.postid, 'title': post.post_title, 'content': post.post_content},
            'comments': serializer.data
        }
    except (KeyError, ValueError, Post.DoesNotExist) as err:
        logging.getLogger('django.request').error(err)
        data = {'code': 20001, 'message': '获取评论数据失败'}
    return Response(data)


class NewsView(ModelViewSet):
    """获得消息"""
    queryset = News.objects.all()
    serializer_class = NewsSerializer


@api_view(('GET',))
def show_users(request):
    """获得用户列表"""
    post = User.objects.all()
    serializer = UserSerializer(post, many=True)
    data = {'code': 10000,
            'post': serializer.data}
    return JsonResponse(data)


@api_view(('POST', ))
def login(request):
    """用户登录"""
    hint = request.GET.get('hint') or ''
    if request.method == 'POST':
        username = request.data.get('username', '').strip()
        password = request.data.get('password', '')
        if check_username(username) and check_password(password):
            password = gen_sha256_digest(password)
            user = User.objects.filter(Q(username=username) | Q(tel=username))\
                .filter(pw=password).first()
            if user:
                user.save()
                payload = {
                    'userid': user.userid,
                    'exp': timezone.now() + timedelta(days=1)
                }
                # 通过PyJWT的encode函数生成用户身份令牌（bytes，可以通过decode方法处理成str）
                token = jwt.encode(payload, settings.SECRET_KEY).decode()
                return Response({'code': 40000, 'hint': '登录成功', 'token': token, 'username': user.username})
            else:
                hint = '登录失败，用户名或密码错误'
        else:
            hint = '请输入有效的登录信息'
    return Response({'code': 40001, 'hint': hint})


def register(request):
    """用户注册"""
    username, tel, hint = '', '', ''
    if request.method == 'POST':
        agreement = request.POST.get('agreement')
        username = request.POST.get('username', '').strip()
        password = request.POST.get('password', '')
        tel = request.POST.get('tel', '').strip()
        if agreement == 'on':
            if check_username(username) and check_password(password) and check_tel(tel):
                    password = gen_sha256_digest(password)
                    try:
                        user = User(username=username, pw=password, tel=tel)
                        # user.last_visit = timezone.now()
                        user.save()
                        hint = '注册成功，请登录'
                        return redirect(f'/static/html/login.html/')
                    except DatabaseError:
                        hint = '注册失败，用户名或手机号已被使用'
            else:
                hint = '请输入有效的注册信息'
        else:
            hint = '请勾选同意网站用户协议及隐私政策'
    return render(request, 'register.html', {'hint': hint, 'username': username, 'tel': tel})


def check_unique(request):
    flag = False
    username = request.GET.get('username', '').strip()
    if check_username(username):
        user = User.objects.filter(username=username).first()
        flag = user is None
    return JsonResponse({'is_valid': flag})


def logout(request):
    """注销（退出登录）"""
    request.session.flush()
    resp = redirect('/')
    resp.delete_cookie('username')
    return resp

